import os

from sc_engine.apps import messages as msgs
from sc_engine.repositories import Repository, use
from sc_engine.repositories.stores import PickleFileStore

from sc_engine.apps.data import NamedAliasedData

class PlayerData(NamedAliasedData):
    """Houses the data for a player."""
    def __init__(self, name, race, aliases = None):
        self.race = race

        super(PlayerData, self).__init__(name, aliases)

def make_app(app_name, root_config, config):
    data_directory = root_config['data_directory']
    store_file = os.path.join(data_directory, app_name)
    store = PickleFileStore(store_file)
    repo = Repository(store)

    app = PlayerDataApp(repo)

    return {
        msgs.PlayerFetchAnnouncement: app.player_fetch_announcement,
        msgs.PlayerFetchNonExistantPlayer: app.player_fetch_non_existant_player,
        msgs.PlayerDataRequested: app.player_data_requested,
        msgs.PlayerNameDetermination: app.player_name_determination,
        msgs.PlayerAliasAddition : app.player_alias_addition,
    }

class PlayerDataApp(object):
    """Control the local storing and distribution of info on players.

    Will send out info for a player when requested, or when the details change.
    If info for a player is requested but no data is known for it, will send
    out a request to fetch it from the kespa web site.
    """
    def __init__(self, repo):
        self.repo = repo

    def _announce(self, players, id):
        p = players[id]

        if p is None:
            return msgs.PlayerDoesNotExistAnnouncement(id)
        else:
            return msgs.PlayerDataAnnouncement(id, p.name, p.race, p.aliases)

    @use('repo', 'players')
    def player_data_requested(self, msg, players):
        if msg.player_id not in players:
            return msgs.PlayerFetchRequested(msg.player_id)

        return self._announce(players, msg.player_id)

    @use('repo', 'players')
    def player_fetch_non_existant_player(self, msg, players):
        players[msg.player_id] = None
        return msgs.PlayerDoesNotExistAnnouncement(msg.player_id)

    @use('repo', 'players')
    def player_fetch_announcement(self, msg, players):
        p = PlayerData(msg.name, msg.race)
        players[msg.player_id] = p

        return self._announce(players, msg.player_id)

    @use('repo', 'players')
    def player_name_determination(self, msg, players):
        players[msg.player_id].determine_name(msg.true_name)
        return self._announce(players, msg.player_id)

    @use('repo', 'players')
    def player_alias_addition(self, msg, players):
        players[msg.player_id].add_alias(msg.alias)
        return self._announce(players, msg.player_id)
